<!DOCTYPE html>
            
<HTML>
<HEAD>
<meta name="booktitle" content="Developing Applications With Objective Caml" >
 <meta charset="ISO-8859-1"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<META name="GENERATOR" content="hevea 1.05-7 of 2000-02-24">
<META NAME="Author" CONTENT="Christian.Queinnec@lip6.fr">
<LINK rel=stylesheet type="text/css" href="videoc-ocda.css">
<script language="JavaScript" src="videoc.js"><!--
//--></script>
<TITLE>
 Sockets
</TITLE>
</HEAD>
<BODY class="regularBody">
<A HREF="book-ora185.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora187.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2> Sockets</H2><A NAME="sec-socket"></A>
<A NAME="@concepts358"></A>
We saw in chapters <A HREF="index.html#chap-PS">18</A> and <A HREF="index.html#chap-PC">19</A> two ways to 
perform interprocess communication, namely, pipes and channels.
These first two methods use a logical model of concurrency.
In general, they do not give better performance to the 
degree that the communicating processes share resources, in particular,
the same processor. The third possibility, which we 
present in this section, uses sockets for communication.
This method originated in the Unix world. Sockets allow
communication between processes executing on the same
machine or on different machines.<BR>
<BR>
<A NAME="toc273"></A>
<H3> Description and Creation</H3>A socket is responsible for establishing communication
with another socket, with the goal of transferring information.
We enumerate the different situations that may be encountered 
as well as the commands and datatypes that are used by 
TCP/IP sockets. The classic metaphor 
is to compare sockets to telephone sets.
<A NAME="@fonctions471"></A>
<A NAME="@fonctions472"></A>
<A NAME="@fonctions473"></A>
<A NAME="@fonctions474"></A>
<UL>
<LI>
 In order to work, the machine must be connected to the network 
(<TT>socket</TT>).

<LI> To receive a call, it is necessary to possess a number of the 
type <I>sock_addr</I> (<TT>bind</TT>).

<LI> During a call, it is possible to receive another call if 
the configuration allows it (<TT>listen</TT>).

<LI> It is not necessary to have one's own number to call 
another set, once the connection is established 
in both directions (<TT>connect</TT>).
</UL>
<H5> Domains.</H5> 
Sockets belong to different domains, according to whether 
they are meant to communicate internally or externally. 
The <TT>Unix</TT> library defines two possible domains corresponding 
to the type constructors:


<PRE><BR># <B>type</B><CODE> </CODE>socket_domain<CODE> </CODE><CODE>=</CODE><CODE> </CODE>PF_UNIX<CODE> </CODE><CODE>|</CODE><CODE> </CODE>PF_INET;;<BR>

</PRE>

<A NAME="@fonctions475"></A>
The first domain corresponds to local communication, and the 
second, to communication over the Internet. 
These are the principal domains for sockets. <BR>
<BR>
In the following, we use sockets belonging only to 
the Internet domain.<BR>
<BR>

<H5> Types and protocols.</H5>Regardless of their domain, sockets define certain communications
properties (reliability, ordering, etc.) represented 
by the type constructors:


<PRE><BR># <B>type</B><CODE> </CODE>socket_type<CODE> </CODE><CODE>=</CODE><CODE> </CODE>SOCK_STREAM<CODE> </CODE><CODE>|</CODE><CODE> </CODE>SOCK_DGRAM<CODE> </CODE><CODE>|</CODE><CODE> </CODE>SOCK_SEQPACKET<CODE> </CODE><CODE>|</CODE><CODE> </CODE>SOCK_RAW<CODE> </CODE>;;<BR>

</PRE>

<A NAME="@fonctions476"></A>
<A NAME="@fonctions477"></A>
According to the type of socket used, the underlying communications protocol 
obeys definite characteristics. Each type of communication 
is associated with a default protocol.<BR>
<BR>
In fact, we will only use the first kind of communication --- 
<TT>SOCK_STREAM</TT> --- with the default protocol TCP. 
This guarantees reliability, order, prevents duplication of
exchanged messages, and works in connected mode.<BR>
<BR>
For more information, we refer the reader to the Unix 
literature, for example [<A HREF="book-ora214.html#Stevens"><CITE>Ste92</CITE></A>].<BR>
<BR>

<H5> Creation.</H5>
The function to create sockets is:


<PRE><BR># Unix.socket<CODE> </CODE>;;<BR><CODE>- : Unix.socket_domain -&gt; Unix.socket_type -&gt; int -&gt; Unix.file_descr = &lt;fun&gt;</CODE><BR>

</PRE>

<A NAME="@fonctions478"></A>
The third argument allows specification of the 
protocol associated with communication.
The value 0 is interpreted as ``the default protocol''
associated with the pair (domain, type) argument 
used for the creation of the socket. 
The value returned by this function is a file descriptor.
Thus such a value can be used with the standard input-output functions
in the <TT>Unix</TT> library.<BR>
<BR>
We can create a TCP/IP socket with: 


<PRE><BR># <B>let</B><CODE> </CODE>s_descr<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Unix.socket<CODE> </CODE>Unix<CODE>.</CODE>PF_INET<CODE> </CODE>Unix<CODE>.</CODE>SOCK_STREAM<CODE> </CODE><CODE>0</CODE><CODE> </CODE>;;<BR><CODE>val s_descr : Unix.file_descr = &lt;abstr&gt;</CODE><BR>

</PRE>
<BR>
<BR>


<H3> Warning </H3> <HR>

Even though the <TT>socket</TT> function returns a value of type
<I>file_descr</I>, the system distinguishes descriptors for a 
files and those associated with sockets. 
You can use the file functions in the <TT>Unix</TT> library with 
descriptors for sockets; but an exception is raised when a classical file 
descriptor is passed to a function expecting a descriptor for a socket.


<HR>

<BR>
<BR>

<H5> Closing.</H5> Like all file descriptors, a socket is closed 
by the function:
<A NAME="@fonctions479"></A>


<PRE><BR># Unix.close<CODE> </CODE>;;<BR><CODE>- : Unix.file_descr -&gt; unit = &lt;fun&gt;</CODE><BR>

</PRE>

<A NAME="@fonctions480"></A>
When a process finishes via a call to <TT>exit</TT>, all open file descriptors
are closed automatically.<BR>
<BR>
<A NAME="toc274"></A>
<H3> Addresses and Connections</H3>A socket does not have an address when it is created.
In order to setup a connection between two sockets, the 
caller must know the address of the receiver. <BR>
<BR>
The address of a socket (TCP/IP) 
consists of an IP address and a port number. 
A socket in the Unix domain consists simply of 
a file name.<BR>
<BR>


<PRE><BR># <B>type</B><CODE> </CODE>sockaddr<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>ADDR_UNIX<CODE> </CODE><B>of</B><CODE> </CODE>string<CODE> </CODE><CODE>|</CODE><CODE> </CODE>ADDR_INET<CODE> </CODE><B>of</B><CODE> </CODE>inet_addr<CODE> </CODE><CODE>*</CODE><CODE> </CODE>int<CODE> </CODE>;;<BR>

</PRE>

<A NAME="@fonctions481"></A><BR>
<BR>

<H5> Binding a socket to an address.</H5>
The first thing to do in order to receive calls after the creation
of a socket is to bind the socket to an address.
This is the job of the function:


<PRE><BR># Unix.bind<CODE> </CODE>;;<BR><CODE>- : Unix.file_descr -&gt; Unix.sockaddr -&gt; unit = &lt;fun&gt;</CODE><BR>

</PRE>

<A NAME="@fonctions482"></A><BR>
<BR>
In effect, we already have a socket descriptor, but 
the address that is associated with it at creation 
is hardly useful, as shown by the following example:


<PRE><BR># <B>let</B><CODE> </CODE><TT>(</TT>addr_in<CODE>,</CODE><CODE> </CODE>p_num<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>match</B><CODE> </CODE>Unix.getsockname<CODE> </CODE>s_descr<CODE> </CODE><B>with</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Unix<CODE>.</CODE>ADDR_INET<CODE> </CODE><TT>(</TT>a<CODE>,</CODE>n<TT>)</TT><CODE> </CODE>-&gt;<CODE> </CODE><TT>(</TT>a<CODE>,</CODE>n<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE> </CODE><CODE>_</CODE><CODE> </CODE>-&gt;<CODE> </CODE>failwith<CODE> </CODE><CODE>"not INET"</CODE><CODE> </CODE>;;<BR><CODE>val addr_in : Unix.inet_addr = &lt;abstr&gt;</CODE><BR><CODE>val p_num : int = 0</CODE><BR># Unix.string_of_inet_addr<CODE> </CODE>addr_in<CODE> </CODE>;;<BR><CODE>- : string = "0.0.0.0"</CODE><BR>

</PRE>
<BR>
<BR>
We need to create a useful address and to associate it with
our socket. We reuse our local address <TT>my_addr</TT> as described 
on page <A HREF="book-ora185.html#val-my-addr">??</A> and choose port 12345 which, 
in general, is unused.


<PRE><BR># Unix.bind<CODE> </CODE>s_descr<CODE> </CODE><TT>(</TT>Unix<CODE>.</CODE>ADDR_INET<TT>(</TT>my_addr<CODE>,</CODE><CODE> </CODE><CODE>1</CODE><CODE>2</CODE><CODE>3</CODE><CODE>4</CODE><CODE>5</CODE><TT>)</TT><TT>)</TT><CODE> </CODE>;;<BR><CODE>- : unit = ()</CODE><BR>

</PRE>
<BR>
<BR>

<H5> Listening and accepting connections.</H5>
It is necessary to use two operations before our 
socket is completely operational to receive calls: define
its listening capacity and allow it to accept connections. Those are the 
respective roles of the two functions:


<PRE><BR># Unix.listen<CODE> </CODE>;;<BR><CODE>- : Unix.file_descr -&gt; int -&gt; unit = &lt;fun&gt;</CODE><BR># Unix.accept<CODE> </CODE>;;<BR><CODE>- : Unix.file_descr -&gt; Unix.file_descr * Unix.sockaddr = &lt;fun&gt;</CODE><BR>

</PRE>

<A NAME="@fonctions483"></A>
<A NAME="@fonctions484"></A><BR>
<BR>
The second argument to the <TT>listen</TT> function gives 
the maximum number of connections.
The call to the <TT>accept</TT> function waits for a connection
request. When <TT>accept</TT> finishes, it returns the descriptor
for a socket, the so-called service socket.
This service socket is automatically linked to an address.
The <TT>accept</TT> function may only be applied to sockets
that have called <TT>listen</TT>, that is,
to sockets that have setup a queue of connection requests.<BR>
<BR>

<H5> Connection requests.</H5>
The function reciprocal to <TT>accept</TT> is;


<PRE><BR># Unix.connect<CODE> </CODE>;;<BR><CODE>- : Unix.file_descr -&gt; Unix.sockaddr -&gt; unit = &lt;fun&gt;</CODE><BR>

</PRE>

<A NAME="@fonctions485"></A><BR>
<BR>
A call to Unix.connect<CODE> </CODE>s_descr<CODE> </CODE>s_addr establishes a 
connection between the local socket s_descr 
(which is automatically bound) and the socket with address 
s_addr (which must exist).<BR>
<BR>

<H5> Communication.</H5> 
From the moment that a connection is established between
two sockets, the processes owning them can communicate 
in both directions.
The input-output functions are those in the <TT>Unix</TT> module, described 
in Chapter&nbsp;<A HREF="index.html#chap-PS">18</A>.<BR>
<BR>
<HR>
<A HREF="book-ora185.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora187.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
